package com.fl.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.SocketException;
import java.text.SimpleDateFormat;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;

import com.fl.dao.ParamDao;
import com.fl.sys.SysConfig;


/**
 * <pre>
 * FTP公共处理类<BR>
 * 
 * <li>定义FTP连接，上传，下载的方法</li> <BR>

 * </pre>
 * @author Neil
 *
 */
public class FtpUtil {

	private static Logger log = Logger.getLogger(FtpUtil.class);
	private static String userName; // FTP 登录用户名
	private static String password; // FTP 登录密码
	private static String ftpserver; // FTP 服务器地址IP地址
	private static String port; // FTP 端口
	private static FTPClient ftpClient = null; // FTP 客户端代理
	// 时间格式化
	private static SimpleDateFormat dateFormat = new SimpleDateFormat(
			"yyyy-MM-dd hh:mm");
	// FTP状态码
	public static int i = 1;
	
	
	/**
	 * 构建FTPUtil，直接使用Sysconfig中初始化的信息构建
	 * 
	 * 暂时弃用
	 */
	public FtpUtil() {
		super();
		try {
			this.userName = ParamDao.getParamTableVal(SysConfig.USER);
			this.password = ParamDao.getParamTableVal(SysConfig.PASSWD);
			this.ftpserver = ParamDao.getParamTableVal(SysConfig.FTP_SERVER);
			this.port = ParamDao.getParamTableVal(SysConfig.FTP_PORT);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		connectServer();
	}

	/**
	 * 构建FTPUtil
	 * 用户名，密码，ip，port信息可从SysConfig中取得
	 * @param username 
	 * 					用户名
	 * @param password 
	 * 					密码
	 * @param ftpserver	
	 * 					FTP的地址
	 * @param port	
	 * 					FTP的端口
	 */
	public FtpUtil(String username, String password, String ftpserver, String port) {
		super();
		this.userName = username;
		this.password = password;
		this.ftpserver = ftpserver;
		this.port = port;
	}
	
	
	/**
	 * 按FTP地址，PORT和用户名，密码 连接到服务器
	 * 
	 * @return 
	 * 			true 连接服务器成功，false 连接服务器失败
	 */
	public static boolean connectServer() {
		boolean flag = true;
		if (ftpClient == null) {
			int reply;
			try {
				ftpClient = new FTPClient();
				ftpClient.setControlEncoding("GBK");
				ftpClient.configure(getFtpConfig());
				ftpClient.connect(ftpserver);
				ftpClient.login(userName, password);
				ftpClient.setDefaultPort(Integer.parseInt(port));
				reply = ftpClient.getReplyCode();
				ftpClient.setDataTimeout(120000);

				if (!FTPReply.isPositiveCompletion(reply)) {
					ftpClient.disconnect();
					log.debug("FTP 服务拒绝连接！");
					flag = false;
				}
				i++;
				log.debug("登录ftp服务器 " + ftpserver + " 完成！");
			} catch (SocketException e) {
				flag = false;
				log.debug("登录ftp服务器 " + ftpserver + " 失败,连接超时！", e);
			} catch (IOException e) {
				flag = false;
				log.debug("登录ftp服务器 " + ftpserver + " 失败，FTP服务器无法打开！", e);
			}
		}

		return flag;
	}
	
	
	/**
	 * 设置FTP客服端的配置--一般可以不设置
	 * 
	 * @return ftpConfig
	 */
	private static FTPClientConfig getFtpConfig() {
		FTPClientConfig ftpConfig = new FTPClientConfig(
				FTPClientConfig.SYST_UNIX);
		ftpConfig.setServerLanguageCode(FTP.DEFAULT_CONTROL_ENCODING);
		return ftpConfig;
	}
	
	
	/**
	 * 获取ftp目录中存在的文件列表
	 * 
	 * @param filePath
	 * 		    需要切换到ftp的目录，若为空则为默认目录
	 * @return 
	 * 			java.util.List 文件列表
	 */
	public static String[] getFtpFileNameList(String filePath) {
		if (ftpClient == null) {
			log.error("ftpClient isn't initialize right.");
			return null;
		}
		
		try {
			log.debug("Get ftp files start.");
			//如果filePath为空，则为登录的目录，否则切换目录
			if (!StringUtil.isBlank(filePath)) {
				ftpClient.changeWorkingDirectory(filePath);
			}
			
			//获取ftpserver中目录中的文件列表
//			FTPFile[] files = ftpClient.listFiles();
//			if (files == null) {
//				return null;
//			} else {
//				List fileLst = new ArrayList();
//				//返回文件名列表
//				for (int i =0, j = files.length; i < j; i++) {
//					String filename = files[i].getName();
//					fileLst.add(filename);
//				}
//				return fileLst;
//			}
			
			String[] files =  ftpClient.listNames();
			if (files == null) {
				log.debug("no files");
				return null;
			} else {
				log.debug("return files. Get ftp files end");
				return files;
			}
		} catch (IOException e) {
			log.error("getFtpFileNameList",e);
		}
		
		return null;
	}
	
	
	/**
	 * 上传文件
	 * 
	 * @param localFilePath
	 *            本地文件路径及名称(例如：E:/dmp/20130101-aa.dmp)
	 * @param remoteFileName
	 *            FTP 服务器文件名称(20130101-aa.dmp)
	 * @param remoteDir
	 *            FTP 服务器目录(例如：/dmp，可不填) 如果ftp服务器text目录不存在，将会自动创建
	 * @return
	 */
	public static boolean uploadFile(String localFilePath,
			String remoteFileName, String remoteDir) {
		openFtpConnection();
		//如果输入目录，但目录不存在，则新增目录
		makeDirs(remoteDir);
		BufferedInputStream inStream = null;
		//返回是否成功标志
		boolean success = false;
		try {
			inStream = new BufferedInputStream(new FileInputStream(
					localFilePath));
			//切换FTP目录到指定目录，如果为空则为当前目录
			changeWorkingDirectory(remoteDir);
			//尝试上传文件
			success = ftpClient.storeFile(remoteFileName, inStream);
		} catch (FileNotFoundException e) {
			log.error("文件未找到", e);
		} catch (IOException e) {
			log.error("IO异常", e);
		} finally {
			if (inStream != null) {
				try {
					//关系流
					inStream.close();
				} catch (IOException e) {
					log.error("uploadFile 读取文件IO异常", e);
				}
			}
		}
		return success;
	}
	
	/**
	 * 创建一个给定的新的子目录路径是在FTP服务器上
	 * 
	 * @param dirPath
	 *            目录名称
	 * @param remoteDir
	 *            ftp目录
	 * @return 状态值 
	 * 			  true 创建成功 false 创建失败
	 */
	public static boolean makeDir(String dirPath, String remoteDir) {
		openFtpConnection();
		boolean success = false;
		try {
			changeWorkingDirectory(remoteDir);
			success = ftpClient.makeDirectory(dirPath);
		} catch (IOException e) {
			log.error("Ftp make dir IO异常", e);
		}
		return success;
	}
	
	
	/**
	 * 进入到服务器的某个目录下
	 * 
	 * @param directory
	 * 					目录名称
	 */
	public static void changeWorkingDirectory(String directory) {
		try {
			connectServer();
			ftpClient.changeWorkingDirectory(directory);
		} catch (IOException ioe) {
			log.debug("登录ftp服务器目录 " + directory + " 失败！", ioe);
		}
	}
	
	
	
	/**
	 * 创建此抽象路径名指定的目录
	 * 
	 * @param remoteDir
	 *            ftp目录(/dmp/201307)
	 * @return 状态值
	 */
	public static boolean makeDirs(String remoteDir) {
		openFtpConnection();
		boolean flag = false;
		String dirs[] = remoteDir.split("/");
		String parentName = "";
		for (int i = 0; i < dirs.length; i++) {
			if (i + 1 != dirs.length) {
				if (i == 0) {
					flag = isExists(dirs[i + 1], "/");
					parentName = "/";
					isCreateDir(flag, dirs[i + 1], parentName);
				} else {
					flag = isExists(dirs[i + 1], parentName + dirs[i]);
					parentName += dirs[i] + "/";
					isCreateDir(flag, dirs[i + 1], parentName);
				}
			}
		}
		return true;
	}
	
	/**
	 * 没有文件夹创建该文件夹
	 * 
	 * @param flag
	 * 			标志，如果是false则创建，true则不处理
	 * @param dirName
	 * 			目录名称
	 * @param remoteDir
	 * 			路径
	 */
	private static void isCreateDir(boolean flag, String dirName,
			String remoteDir) {
		if (!flag) {
			openFtpConnection();
			makeDir(dirName, remoteDir);
		}
	}
	
	
	/**
	 * 代替检查目录或文件是否存在
	 * 
	 * @param dirName
	 *            本地目录名称(d:f.txt)
	 * @param remoteDir
	 *            ftp目录名称(/f)
	 * @return 状态
	 */
	public static boolean isExists(String dirName, String remoteDir) {
		openFtpConnection();
		boolean falg = false;
		try {
			FTPFile[] ftpFiles = ftpClient.listFiles(remoteDir);
			if (ftpFiles == null) {
				return false;
			}
			for (int i = 0; i < ftpFiles.length; i++) {
				FTPFile file = (FTPFile) ftpFiles[i];
				if (file.isDirectory()) {
					if (dirName.equals(file.getName().toString()))
						return true;
				}
			}
		} catch (IOException e) {
			log.debug("isExists is error", e);
		}
		return falg;
	}
	
	/**
	 * 检查FTP 是否关闭 ，如果关闭打开FTP
	 * 
	 * @throws Exception
	 */
	public static boolean openFtpConnection() {
		if (null == ftpClient)
			return false;
		boolean flag = true;
		try {
			if (!ftpClient.isConnected()) {
				flag = connectServer();
			}
		} catch (Exception e) {
			e.printStackTrace();
			flag = false;
		}
		return flag;
	}
	
	
	/**
	 * 下载文件(单个)
	 * 
	 * @param remoteFileName
	 *            	服务器上的文件名 (20130101-aa.dmp)
	 * @param localFileName	
	 * 				本地文件路径及文件名(E:/dmp/20130101-aa.dmp)
	 * @param remoteDir
	 * 				ftp目录（/dmp）
	 * @return
	 * 			 下载到本地的文件名（E:/dmp/20130101-aa.dmp）
	 */
	public static String downloadFile(String remoteFileName, String localFileName,
			String remoteDir) {
		openFtpConnection();
		BufferedOutputStream buffOut = null;
		try {
			changeWorkingDirectory(remoteDir);
			buffOut = new BufferedOutputStream(new FileOutputStream(
					localFileName));
			//从ftp上接收文件
			ftpClient.retrieveFile(remoteFileName, buffOut);
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		} finally {
			try {
				if (buffOut != null)
					buffOut.close();
			} catch (Exception e) {
				log.error("", e);
			}
		}
		return localFileName;
	}
	
	
	/**
	 * 删除一个文件
	 * 
	 * @param remoteFileName
	 *            删除的文件名称
	 * @param remoteDir
	 *            删除文件所在服务器上的目录
	 * @return true 删除成功 false 删除失败
	 */
	public static boolean deleteFile(String remoteFileName, String remoteDir) {
		openFtpConnection();
		try {
			changeWorkingDirectory(remoteDir);
			//删除文件
			ftpClient.deleteFile(remoteFileName);
			return true;
		} catch (IOException e) {
			log.error("", e);
		}
		return false;
	}
	
	
	/**
	 * 删除目录(及目录下所有文件和子目录)
	 * 
	 * @param path
	 *            ftp删除目录路径
	 * @return true 删除成功 false 删除失败
	 */
	public static boolean removeDirectory(String path) {
		openFtpConnection();
		boolean flag = false;
		try {
			FTPFile[] ftpFileArr = ftpClient.listFiles(path);
			if (ftpFileArr == null || ftpFileArr.length == 0) {
				return deleteEmptyDirectory(path);
			}
			for (FTPFile ftpFile : ftpFileArr) {
				String name = ftpFile.getName();
				if (".".equals(name) || "..".equals(name)) {
					continue;
				}
				if (ftpFile.isDirectory()) {// 文件夹递归删除
					removeDirectory(path + "/" + name);
				} else {
					deleteFile(name, path);
				}
			}

			flag = ftpClient.removeDirectory(path);
		} catch (IOException e) {
			log.debug("", e);
		}
		return flag;
	}
	
	
	/**
	 * 删除空目录
	 * 
	 * @param remoteDir
	 *            ftp目标路径
	 * @return 
	 * 			true 删除空目录成功 ,false 删除失败
	 */
	public static boolean deleteEmptyDirectory(String remoteDir) {
		openFtpConnection();
		boolean falg = false;
		try {
			ftpClient.removeDirectory(remoteDir);
			falg = true;
		} catch (IOException e) {
			log.debug("", e);
		}
		return falg;

	}
	
	/**
	 * 检查目录(或文件)是否存在
	 * 
	 * @param path
	 *            （/dmp）
	 * @return
	 */
	public boolean existDirectory(String path) {
		openFtpConnection();
		boolean flag = false;
		try {
			FTPFile[] ftpFileArr = ftpClient.listFiles(path);
			for (FTPFile ftpFile : ftpFileArr) {
				if (ftpFile.isDirectory()
						&& ftpFile.getName().equalsIgnoreCase(path)) {
					flag = true;
					break;
				}
			}
			return flag;
		} catch (IOException e) {
			log.debug("", e);
		}
		return flag;
	}
	
	/**
	 * 返回 ftp路径
	 * 
	 * @param remoteDir
	 *            ftp路径
	 * @return
	 */
	public static String getFtpPath(String remoteDir) {
		openFtpConnection();
		try {
			ftpClient.changeWorkingDirectory(remoteDir);
			return ftpClient.printWorkingDirectory();
		} catch (IOException e) {
			log.error("", e);
		}
		return null;
	}
	
	
	/**
	 * 返回到上一层目录
	 * 
	 * @param remoteDir
	 *            ftp路径
	 */
	public static String changeToParentDirectory(String remoteDir) {
		openFtpConnection();
		try {
			ftpClient.changeWorkingDirectory(remoteDir);
			ftpClient.changeToParentDirectory();
			return ftpClient.printWorkingDirectory();
		} catch (IOException e) {
			log.error("", e);
		}
		return null;
	}
	
	
	/**
	 * 关闭连接
	 */
	public static void closeConnect() {
		try {
			if (ftpClient != null) {
				ftpClient.logout();
				ftpClient.disconnect();
			}
		} catch (Exception e) {
			log.debug("关闭ftp服务器 " + ftpserver + " 失败，FTP服务器无法打开！", e);
		}
	}
	
	
	/**
	 * 重命名文件
	 * 
	 * @param oldFileName
	 *            	原文件名
	 * @param newFileName
	 *            	新文件名
	 */
	public static void renameFile(String oldFileName, String newFileName) {
		try {
			connectServer();
			ftpClient.rename(oldFileName, newFileName);
		} catch (IOException e) {
			log.debug("", e);
		}
	}
	
	
	/**
	 * 设置传输文件的类型[文本文件或者二进制文件]
	 * 
	 * @param fileType
	 * 				BINARY_FILE_TYPE、ASCII_FILE_TYPE
	 * 
	 */
	public static void setFileType(int fileType) {
		try {
			connectServer();
			ftpClient.setFileType(fileType);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 返回FTPClient，若Util不满足，可独立写应用内容
	 * 
	 * @return ftpClient
	 */
	protected static FTPClient getFtpClient() {
		connectServer();
		return ftpClient;
	}
}
